/**
 * \file sgi_link_layer.h
 *
 * \brief declaration file of SGI library to handle the sgi link layer bursts
 *
 * \author Santiago Carmona Meco
 *
 * Contact santiago.carmonads@gmail.com
 *
 */

// ****************************************
// 	CHANGE LOG
//                OCT-2011  scarmona  Creating this file
//                2011-2012 scarmona  Development of the library and source code modifications
//                FEB-2013  scarmona  Modifications of type names, variable names and update
// 									  of comments with format of doxygen
//				  26-4-2013 scarmona  Subtle modifications of code style and type definitions in burst structs
//				  21-6-2013 scarmona  Changes in parameters of builder functions
//
// ****************************************

#ifndef __SGI_HUMSAT_BURST_H_
#define __SGI_HUMSAT_BURST_H_


#include <public/basic_types.h>
#include <public/crc_16.h>


//masks for flags of the CTRL field
//TODO: Contemplar la posibilidad de sustituir por const
#define MASK_ACK_SGI 0x01
#define MASK_YIELD_SGI 0x02
#define MASK_SPACE_SGI 0x04
#define MASK_GROUND_SGI 0x08
#define MASK_DATA_SGI 0x10
#define MASK_ALT_SGI 0x20
#define MASK_REP_SGI 0x40

//masks for different codes of the CODE field
#define MASK_BURST_A_SGI 0x0A
#define MASK_BURST_B_SGI 0x0B
#define MASK_BURST_C_SGI 0x0C
#define MASK_BURST_D_SGI 0x0D
#define MASK_BURST_E_SGI 0x0E
#define MASK_BURST_F_SGI 0x0F

// burst's masks
#define MASK_SRG_HUMSAT_READY 0x07
#define MASK_SAT_BURST_NACK 0x08

//Satellite Control masks
#define MASK_SAT_TC_FRAMES 0x19 //		  00011001	-- X0X110X1 -> 00011001
#define MASK_LAST_SAT_TC_FRAMES 0x1B //   00011011	-- X0X11011 -> 00011011
#define MASK_SAT_TM_FRAMES 0x15 // 		  00010101	-- TODO: MASK_SAT_TM_FRAMES 0xX5==MASK_SAT_TC_FRAMES_ACK 0xX5 con y sin dato
#define MASK_LAST_SAT_TM_FRAMES 0x17 //	  00010111	-- 00010111 el segundo bit es para el campo Yield, que indica que es la última TM
#define MASK_SAT_TM_FRAMES_ACK 0x09// 	  00001001	--
#define MASK_LAST_SAT_TM_FRAMES_ACK 0x0B//00001011 	--
#define MASK_SAT_TC_FRAMES_ACK 0x05// 	  00000101	--

//Sensor  TMTC Delivery Service masks
#define MASK_SEN_TMTC_DEL_REQ 0x0B 				//  TIPO B
#define MASK_SEN_TMTC_DEL_ACCEPT 0x07			//  TIPO B

#define MASK_SEN_TMTC_DEL_END 0x07 				//  TIPO E
#define MASK_SEN_TMTC_DEL_END_ACK 0x0B 			//  TIPO E

#define MASK_SEN_TC_SGI_LINK_FRAMES 0x19 		//  TIPO C
#define MASK_SEN_LAST_TC_SGI_LINK_FRAMES 0x1B 	//  TIPO C
#define MASK_SEN_TM_SGI_LINK_FRAMES 0x15		//  TIPO C
#define MASK_SEN_LAST_TM_SGI_LINK_FRAMES 0x17	//  TIPO C
#define MASK_SEN_TM_SGI_LINK_FRAMES_ACK 0x09	//  TIPO C
#define MASK_SEN_LAST_TM_SGI_LINK_FRAMES_ACK 0x0B	//  TIPO C
#define MASK_SEN_TC_SGI_LINK_FRAMES_ACK 0x05	//  TIPO C

#define LENGTH_DATA_FRAMES_IN_WORDS 4096
#define LENGTH_FINAL_FRAMES_IN_WORDS 4112

typedef enum BurstTypeReceived  {BurstTypeIsSGIDefault
				,BurstTypeIsSrgHumsatReady
				,BurstTypeIsSatBurstNack
				,BurstTypeIsSatTCFrames
				,BurstTypeIsSatTMFrames
				,BurstTypeIsSatTCFramesAck
				,BurstTypeIsSatTMFramesAck
				,BurstTypeIsSenTMTCDelReq
				,BurstTypeIsSenTMTCDelAccept
				,BurstTypeIsSenTMTCDelEnd
				,BurstTypeIsSenTMTCDelEndAck
				,BurstTypeIsSenTCSgiLinkFrames
				,BurstTypeIsSenTMSgiLinkFrames
				,BurstTypeIsSenTCSgiLinkFramesAck
				,BurstTypeIsSenTMSgiLinkFramesAck} BurstTypeReceived_t;


typedef struct sgi_link_layer_burst_info_type_a
{//A Y C son iguales...
    byte_t univ_time[4];//universal time
    byte_t  dummy[3];
    byte_t nf;//number of frames included in the burst after the header
}
SGI_burst_A_t;

typedef struct sgi_link_layer_burst_info_type_b
{
    byte_t size_req[4];//size requested (satellite or ground station) in packs of 256 bytes
    byte_t size_provide[4];//size provided by the satellite or the station in packs of 256 bytes
}
SGI_burst_B_t;


typedef struct sgi_link_layer_burst_info_type_c
{
    byte_t acks[4];
    byte_t  dummy[3];
    byte_t nf;
}
SGI_burst_C_t;

typedef struct sgi_link_layer_burst_info_type_d
{
    byte_t acks[4];
    byte_t  gc;//ground client
    byte_t  ss;//satellite subSys
    byte_t  sd;//subSys Device
    byte_t nf;
}
SGI_burst_D_t;


typedef struct sgi_link_layer_burst_info_type_e
{
    byte_t stats_tx[4];//total of transmited packs (satellite or ground station)
    byte_t stats_rx[4];//total of received packs (satellite or ground station)
}
SGI_burst_E_t;

typedef struct sgi_link_layer_burst_info_type_f
{
    byte_t dummy[8];
}
SGI_burst_F_t;



union sgi_link_layer_burst_type_info_t
{
	SGI_burst_A_t type_a_info;
	SGI_burst_B_t type_b_info;
	SGI_burst_C_t type_c_info;
	SGI_burst_D_t type_d_info;
	SGI_burst_E_t type_e_info;
	SGI_burst_F_t type_f_info;
};

typedef struct sgi_link_layer_burst_info_t
{
	byte_t code;
	byte_t crtl;
	byte_t key[4];
	union sgi_link_layer_burst_type_info_t burst_type_info;
}
SGI_burst_t;

typedef struct sgi_link_layer_sen_tc_frame_t
{
	byte_t  length;
	word16_t sensor_id;
	byte_t  data[30];
	word16_t crc;

}
SGI_sen_tc_frame_t;

/**
 * \brief This function gets the burst info for each type of burst
 *
 * \param pBurstHeader bytes of the complete burst header
 * \param burstInfo struct where the header burst values are copied
 */
//void sgi_link_layer_get_burst_info_type (byte_t * pBurstHeader,SGI_burst_t * pBurstInfo);



//TODO: revisar, esta función no se usa para nada
/**
 * \brief checks crc and get burst info
 *
 * \param pBurstHeader bytes of the complete burst header
 * \param burstInfo struct where the header burst values are copied
 *
 * \return true if crc is OK
 */
bool_t sgi_link_layer_get_burst_info(byte_t * pBurstHeader,SGI_burst_t * pBurstInfo);


/**
 * \brief checks CRC field and return true if is OK
 *
 * \param pBurstHeader bytes of the complete burst header
 * \param this param allow knowing which of both headers is used,
 * due to the need of work with the redundant header in case of the first is wrong
 *
 * \return true if crc is OK
 */
bool_t sgi_link_layer_check_crcs(byte_t * pBurstHeader,int8_t *offSet);

/**
 * \brief function that adds the CRC field to the final burst
 *  used within the function that builds the plot
 *
 * \param pBurstHeader bytes of the complete burst header
 */
void sgi_link_layer_add_crc_to_frame(byte_t * pBurstHeader);

/**
* \brief gets code of the burst header
*
* \param pBurstHeader bytes of the complete burst header
*
* \return returns the code field
*/
byte_t sgi_link_layer_get_code(byte_t * pBurstHeader);


/**
* \brief gets ctrl flags of the burst header
*
* \param pBurstHeader bytes of the complete burst header
*
* \return returns the ctrl flags field
*/
byte_t sgi_link_layer_get_ctrl_flags(byte_t * pBurstHeader);

/**
* \brief gets key field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
* \param pKey through of this parameter will be return the key field value
*/
void sgi_link_layer_get_key(byte_t * pBurstHeader, byte_t *pKey);


/**
* \brief gets univ time code field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
* \param pUnivTime through of this parameter will be return the UnivTime field value
*/
void sgi_link_layer_get_univ_time(byte_t * pBurstHeader, byte_t *pUnivTime);

/**
* \brief gets size req code field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
* \param pSizeCode through of this parameter will be return the SizeReq field value
*/
void sgi_link_layer_get_size_req_2(byte_t * pBurstHeader, byte_t *pSizeReq);
word32_t sgi_link_layer_get_size_req(byte_t * pBurstHeader);


/**
* \brief gets stats tx code field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
* \param pStatsTx through of this parameter will be return the StatsTx field value
*/
void sgi_link_layer_get_stats_tx(byte_t * pBurstHeader, byte_t *pStatsTx);


/**
* \brief gets stats rx code field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
* \param pStatsRx through of this parameter will be return the StatsRx field value
*/
void sgi_link_layer_get_stats_rx(byte_t * pBurstHeader, byte_t *pStatsRx);


/**
* \brief gets acks field from sgi_link_layer
* \param pBurstHeader  pointer to frame
* \param pAcks pointer where acks field is copied
*/
void sgi_link_layer_get_acks_2(byte_t * pBurstHeader, byte_t *pAcks);//TODO: comprobar si se utiliza y eliminar

/**
* \brief gets acks field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
*
* \return a word32 with the value of acks field
*/
word32_t sgi_link_layer_get_acks(byte_t * pBurstHeader);



/**
* \brief size provide field from sgi_link_layer
* \param pBurstHeader  pointer to frame
* \param pSizeProvide pointer where size provide field is copied
*/
void sgi_link_layer_get_size_provide_2(byte_t * pBurstHeader, byte_t *pSizeProvide);//TODO: comprobar si se utiliza y eliminar


/**
* \brief gets size provide field of the burst header
*
* \param pBurstHeader bytes of the complete burst header
*
* \return a word32 with the value of SizeProvide field
*/
word32_t sgi_link_layer_get_size_provide(byte_t * pBurstHeader);


/**
* \brief gets crc from sgi_link_layer
*
* \param pBurstHeader bytes of the complete burst header
*
* \return a word16 with the Crc field value
*/
word16_t sgi_link_layer_get_crc(byte_t *pBurstHeader);

/**
* \brief get nf from sgi_link_layer
* \param pBurstHeader  pointer to frame
* \return nf
*/
byte_t sgi_link_layer_get_nf(byte_t * pBurstHeader);


/**
* \brief get gc from sgi_link_layer
* \param pBurstHeader  pointer to frame
* \return gc
*/
byte_t sgi_link_layer_get_gc(byte_t * pBurstHeader);
/**
* \brief get ss from sgi_link_layer
* \param pBurstHeader  pointer to frame
* \return ss
*/
byte_t sgi_link_layer_get_ss(byte_t * pBurstHeader);
/**
* \brief get sd from sgi_link_layer
* \param pBurstHeader  pointer to frame
* \return sd
*/
byte_t sgi_link_layer_get_sd(byte_t * pBurstHeader);




/**
* \brief check if ack flag is true
* \param pBurstHeader  pointer to frame
* \return true if ack field is 1, false if not
*/
bool_t sgi_link_layer_is_ack(byte_t * pBurstHeader);


/**
* \brief check if yield flag is true
* \param pBurstHeader  pointer to frame
* \return true if yield field is 1, false if not
*/
bool_t sgi_link_layer_is_yield(byte_t * pBurstHeader);

/**
* \brief check if space flag is true
* \param pBurstHeader  pointer to frame
* \return true if space field is 1, false if not
*/
bool_t sgi_link_layer_is_space(byte_t * pBurstHeader);


/**
* \brief check if ground flag is true
* \param pBurstHeader  pointer to frame
* \return true if ground field is 1, false if not
*/
bool_t sgi_link_layer_is_ground(byte_t * pBurstHeader);

/**
* \brief check if data flag is true
* \param pBurstHeader  pointer to frame
* \return true if data field is 1, false if not
*/
bool_t sgi_link_layer_is_data(byte_t * pBurstHeader);

/**
* \brief check if alt flag is true
* \param pBurstHeader  pointer to frame
* \return true if alt field is 1, false if not
*/
bool_t sgi_link_layer_is_alt(byte_t * pBurstHeader);

/**
* \brief check if rep flag is true
* \param pBurstHeader  pointer to frame
* \return true if rep field is 1, false if not
*/
bool_t sgi_link_layer_is_rep(byte_t * pBurstHeader);



bool_t sgi_link_layer_is_sat_burst_nack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_srg_humsat_ready(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sat_tc_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_last_sat_tc_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sat_tm_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_last_sat_tm_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sat_tm_frames_ack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_last_sat_tm_frames_ack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sat_tc_frames_ack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tmtc_del_req(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tmtc_del_accept(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tmtc_del_end(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tmtc_del_end_ack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tc_sgi_link_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_last_sen_tc_sgi_link_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tm_sgi_link_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_last_sen_tm_sgi_link_frames(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_last_sen_tm_sgi_link_frames_ack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tc_sgi_link_frames_ack(byte_t *pBurstHeader);

bool_t sgi_link_layer_is_sen_tm_sgi_link_frames_ack(byte_t *pBurstHeader);



/*
 * \function to build the type_a_info from the final burst
 */
void sgi_link_layer_build_header_burst_type_a (byte_t * pBurstHeader,SGI_burst_A_t  burst);

/*
 * \function to build the type_b_info from the final burst
 */
void sgi_link_layer_build_header_burst_type_b (byte_t * pBurstHeader,SGI_burst_B_t   burst);

/*
 * \function to build the type_c_info from the final burst
 */
void sgi_link_layer_build_header_burst_type_c (byte_t * pBurstHeader,SGI_burst_C_t   burst);

/*
 * \function to build the type_d_info from the final burst
 */
void sgi_link_layer_build_header_burst_type_d (byte_t * pBurstHeader,SGI_burst_D_t   burst);

/*
 * \function to build the type_e_info from the final burst
 */
void sgi_link_layer_build_header_burst_type_e (byte_t * pBurstHeader,SGI_burst_E_t   burst);

/*
 * \function to build the type_f_info from the final burst
 */
void sgi_link_layer_build_header_burst_type_f (byte_t * pBurstHeader,SGI_burst_F_t   burst);


BurstTypeReceived_t sgi_link_layer_get_burst_type(byte_t * pBurstHeader);
/**
 * \function to build the final burst
 */
void sgi_link_layer_build_header_burst(byte_t * pBurstHeader, SGI_burst_t  burst);

void sgi_link_layer_build_sgi_ready_burst(byte_t *readyBurst,byte_t numberOfFrames,bool_t alt,byte_t *pAltBit);

void sgi_link_layer_build_final_frame(word16_t *pHeader, word16_t *pFrames, word16_t *finalFrame);

void sgi_link_layer_build_tc_ack(byte_t *pHeaderBurst,word32_t acks,bool_t alt,int32_t tryNumber,byte_t *pAltBit);

void sgi_link_layer_build_header_tm_frame(byte_t *pHeaderBurst, word32_t acks, byte_t numberOfFrames, bool_t alt, int32_t tryNumber, byte_t *pAltBit);

void sgi_link_layer_build_header_tc_frame(byte_t *pHeaderBurst,byte_t numberOfFrames);

void sgi_link_layer_build_tm_ack(byte_t *pHeaderBurst,word32_t acks,bool_t last);

word32_t  set_acks(bool_t *pAcksOk);

void sgi_link_layer_build_sen_tm_tc_del_accept (byte_t *pHeaderBurst,bool_t alt,int32_t tryNumber,byte_t *pAltBit,word32_t sizeReq, word32_t sizeProvide);

void sgi_link_layer_build_sen_tm_tc_del_req (byte_t *pHeaderBurst,word32_t sizeReq, word32_t sizeProvide);

void sgi_link_layer_build_sen_tm_tc_del_end (byte_t *pHeaderBurst,bool_t alt,int32_t tryNumber,byte_t *pAltBit);

void sgi_link_layer_build_sen_tm_tc_del_end_ack(byte_t *pHeaderBurst);

/*
 * Functions to build TM and TC SEN_SGI_LINK_FRAMES
 */

void sgi_link_layer_build_sen_tc_sgi_header_frame  (byte_t *pHeaderBurst,byte_t numberOfFrames,bool_t alt,byte_t *pAltBit,word32_t acks);


void sgi_link_layer_build_sen_tm_sgi_header_frame (byte_t *pHeaderBurst,byte_t numberOfFrames,bool_t alt,int32_t tryNumber,byte_t *pAltBit,word32_t acks);

void sgi_link_layer_build_sen_tm_sgi_frames_ack (byte_t *pHeaderBurst,word32_t acks,bool_t last);

void sgi_link_layer_build_sen_tc_sgi_frames_ack (byte_t *pHeaderBurst,word32_t acks,bool_t alt,int32_t tryNumber,byte_t *pAltBit);



byte_t sgi_link_layer_changes_alt_bit (byte_t * ctrlFlags,byte_t altBit);

#endif /* __SGI_TMTC_DELIVERY_SSERVICE_H_ */
